//
//  File Name   :   Clock.CPP
//  Description :   Source code for the Clock class
//  Author      :   William McVicar
//  Email       :   mcvicar.william@gmail.com
//


// Library Includes
#include "CommonDefines.h"

// Local Includes

// This Include
#include "Clock.h"

// Namespaces

// Static Variables
const unsigned int FRAMERATE_COUNT_CYCLE = 100;

// Static Function Prototypes

// Implementation

namespace Protein
{

/**
*	Constructor for the Clock object
*
*	@Author William McVicar
*/
Clock::Clock()
: m_bUsingQPF			( false )
, m_bInPlay				( false )
, m_uiTick				(   0   )
, m_uiLastTick			(   0   )
, m_uiFRCount			(   0   )
, m_fFrameRate			( 0.0f  )
, m_fFrameRateAggregator( 0.0f  )
, m_llQPFTicksPerSec	(   0   )
, m_llStopTime			(   0   )
, m_llQPFLastTick		(   0   )
, m_llBaseTime			(   0   )
, m_llQPFTick			(   0   )
{
	//
}

Clock::Clock(const Clock &)
{

}

Clock&
Clock::operator =( const Clock&  )
{
	return *this;
}

/**
*	This function processes the clock
*
*	@Author William McVicar
*/
void
Clock::Update()
{
	m_uiLastTick = m_uiTick;
	m_uiTick = timeGetTime();

	m_llQPFLastTick = m_llQPFTick;

	LARGE_INTEGER qwTime;
	QueryPerformanceCounter( &qwTime );
	m_llQPFTick = qwTime.QuadPart;

	if(m_uiLastTick == 0)
		m_uiLastTick = m_uiTick;

	if( m_llQPFLastTick == 0 )
		m_llQPFLastTick = m_llQPFTick;

	m_fFrameRateAggregator += static_cast<float>(m_uiTick - m_uiLastTick) / 1000.0f;
	m_uiFRCount++;

	if(m_uiFRCount > FRAMERATE_COUNT_CYCLE)
	{
		m_fFrameRate = static_cast<float>(m_uiFRCount) / m_fFrameRateAggregator;

		m_fFrameRateAggregator = 0;
		m_uiFRCount = 0;
	}
}

/**
*	This function initialises the clock
*
*	@return True upon success, false upon failure.
*	@author William McVicar
*/
bool
Clock::Initialise()
{
	m_bUsingQPF = false;

	m_llQPFTicksPerSec = 0;
	m_llStopTime = 0;
	m_llQPFLastTick = 0;
	m_llBaseTime = 0;
	m_llQPFTick = 0;

	//
	//	Use QueryPerformanceFrequency() to get frequency of timer.  
	//
	LARGE_INTEGER qwTicksPerSec;
	m_bUsingQPF =(bool)(QueryPerformanceFrequency( &qwTicksPerSec ) != 0);
	m_llQPFTicksPerSec = qwTicksPerSec.QuadPart;

	LARGE_INTEGER qwTime;
	QueryPerformanceCounter( &qwTime );
	m_llBaseTime = qwTime.QuadPart;
	m_llQPFTick  = qwTime.QuadPart;

	m_uiTick = timeGetTime();
	m_uiStartTick = m_uiTick;

	return(true);
}

void
Clock::Reset()
{
	Initialise();
}

double
Clock::GetTimeAbsoluteD()
{
	if( !m_bUsingQPF )
	{
		return( -1.0 );
	}

	// Get either the current time or the stop time
	LARGE_INTEGER qwTime;

	if( m_llStopTime != 0 )
	{
		qwTime.QuadPart = m_llStopTime;
	}
	else
	{
		QueryPerformanceCounter( &qwTime );
	}

	double fTime =(double)(qwTime.QuadPart - m_llBaseTime) /(double)m_llQPFTicksPerSec;

	return( fTime );
}

}